#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
DeepSeek API封装模块的集成测试
模拟实际使用场景，测试完整的文本补充分析流程
"""

import unittest
import os
import json
from unittest.mock import patch, MagicMock
import pandas as pd
import requests

from src.text.deepseek_api import DeepSeekTextCompleter, get_text_completer


class IntegrationTestDeepSeekApi(unittest.TestCase):
    """
    DeepSeek API的集成测试
    """
    
    def setUp(self):
        """
        每个测试前的设置
        """
        self.api_key = os.environ.get('DEEPSEEK_API_KEY', 'test_api_key')  # 优先使用环境变量中的API密钥
        self.sample_data_path = os.path.join(os.path.dirname(__file__), 'data', 'test_sample_data.csv')
        self.test_video_id = "test_video_001"
        
        # 准备测试样本数据
        self._prepare_test_sample_data()
        
        # 模拟的视觉分析结果（更接近真实场景的数据结构）
        self.mock_vision_results = {
            "video_id": self.test_video_id,
            "analysis_timestamp": "2024-01-15T10:30:00",
            "analysis": {
                "视频标题": {
                    "value": "跳舞短视频",
                    "confidence": 95,
                    "source": "vision_model"
                },
                "视频分类": {
                    "value": "舞蹈",
                    "confidence": 75,  # 置信度较低，需要补充
                    "source": "vision_model"
                },
                "视频标签": {
                    "value": ["舞蹈", "音乐"],
                    "confidence": 80,
                    "source": "vision_model"
                },
                "场景类型": {
                    "value": None,  # 未识别，需要补充
                    "confidence": 0,
                    "source": "vision_model"
                },
                "人物数量": {
                    "value": 1,
                    "confidence": 90,
                    "source": "vision_model"
                }
            }
        }
    
    def _prepare_test_sample_data(self):
        """
        准备测试用的样本数据
        """
        # 创建测试数据目录
        os.makedirs(os.path.dirname(self.sample_data_path), exist_ok=True)
        
        # 创建测试样本数据
        test_data = {
            "视频ID": ["test_video_001", "test_video_002", "test_video_003"],
            "标题": ["热门舞蹈短视频", "搞笑段子集锦", "美食制作教程"],
            "分类": ["娱乐舞蹈", "搞笑", "美食"],
            "描述": [
                "这段舞蹈视频在抖音上很火，展现了现代流行舞蹈动作",
                "收集了最近网络上热门的搞笑视频片段",
                "详细讲解了家常菜的制作步骤和技巧"
            ],
            "标签": ["舞蹈,潮流,年轻", "搞笑,幽默,段子", "美食,烹饪,教程"],
            "播放量": [100000, 85000, 67000],
            "发布日期": ["2024-01-10", "2024-01-11", "2024-01-12"]
        }
        
        # 保存为CSV文件
        df = pd.DataFrame(test_data)
        df.to_csv(self.sample_data_path, index=False, encoding='utf-8')
    
    def tearDown(self):
        """
        每个测试后的清理
        """
        # 删除测试样本数据文件
        if os.path.exists(self.sample_data_path):
            os.remove(self.sample_data_path)
        
        # 清理全局实例
        import src.text.deepseek_api
        src.text.deepseek_api._text_completer_instance = None
    
    def test_end_to_end_supplement_flow(self):
        """
        测试完整的补充分析流程（使用模拟的API响应）
        """
        # 模拟API响应
        mock_api_response = {
            "choices": [
                {
                    "message": {
                        "content": json.dumps({
                            "supplement_fields": {
                                "视频分类": {
                                    "value": "娱乐舞蹈",
                                    "confidence": 92,
                                    "reasoning": "结合视觉分析结果和样本数据，该视频更精确的分类应为娱乐舞蹈"
                                },
                                "场景类型": {
                                    "value": "室内",
                                    "confidence": 85,
                                    "reasoning": "根据常见舞蹈视频的场景特点和样本数据中的相关信息推断"
                                },
                                "视频标签": {
                                    "value": ["舞蹈", "音乐", "潮流", "年轻"],
                                    "confidence": 88,
                                    "reasoning": "在视觉识别的基础上，结合样本数据补充了潮流和年轻标签"
                                }
                            },
                            "overall_analysis": "这是一段流行舞蹈视频，展现了现代年轻人喜爱的舞蹈风格，场景为室内环境。"
                        })
                    }
                }
            ]
        }
        
        # 创建实例并执行测试
        with patch('requests.post', return_value=MagicMock(json=lambda: mock_api_response, raise_for_status=lambda: None)):
            completer = DeepSeekTextCompleter(self.api_key, self.sample_data_path)
            result = completer.supplement_analysis(self.test_video_id, self.mock_vision_results)
        
        # 验证结果
        self.assertIn('text_supplement', result)
        self.assertIn('supplement_fields', result['text_supplement'])
        self.assertIn('overall_analysis', result['text_supplement'])
        
        # 验证补充的字段
        self.assertEqual(result['analysis']['视频分类']['value'], '娱乐舞蹈')
        self.assertEqual(result['analysis']['视频分类']['confidence'], 92)
        self.assertEqual(result['analysis']['视频分类']['source'], 'text_supplement')
        
        self.assertEqual(result['analysis']['场景类型']['value'], '室内')
        self.assertEqual(result['analysis']['场景类型']['confidence'], 85)
        
        self.assertEqual(len(result['analysis']['视频标签']['value']), 4)  # 增加了两个标签
    
    def test_with_real_sample_data(self):
        """
        测试使用真实的样本数据查找功能
        """
        # 创建实例
        completer = DeepSeekTextCompleter(self.api_key, self.sample_data_path)
        
        # 查找样本数据
        sample_record = completer.find_video_sample(self.test_video_id)
        
        # 验证样本数据查找结果
        self.assertIsNotNone(sample_record)
        self.assertEqual(sample_record['标题'], '热门舞蹈短视频')
        self.assertEqual(sample_record['分类'], '娱乐舞蹈')
        self.assertIn('抖音', sample_record['描述'])
    
    def test_prompt_generation_with_sample(self):
        """
        测试使用样本数据生成提示词
        """
        # 创建实例
        completer = DeepSeekTextCompleter(self.api_key, self.sample_data_path)
        
        # 模拟API响应
        with patch('requests.post', return_value=MagicMock(json=lambda: {"choices": []}, raise_for_status=lambda: None)):
            # 先查找样本数据
            sample_record = completer.find_video_sample(self.test_video_id)
            
            # 生成提示词
            prompt = completer.generate_supplement_prompt(self.test_video_id, self.mock_vision_results, sample_record)
        
        # 验证提示词包含样本数据中的信息
        self.assertIn('热门舞蹈短视频', prompt)
        self.assertIn('娱乐舞蹈', prompt)
        self.assertIn('抖音', prompt)
        
        # 验证提示词包含需要补充的字段
        self.assertIn('视频分类', prompt)
        self.assertIn('场景类型', prompt)
    
    def test_singleton_pattern(self):
        """
        测试单例模式的正确实现
        """
        # 获取两个实例
        instance1 = get_text_completer(api_key=self.api_key, sample_data_path=self.sample_data_path)
        instance2 = get_text_completer(api_key="different_key", sample_data_path="different_path")  # 即使参数不同
        
        # 验证是同一个实例
        self.assertIs(instance1, instance2)
    
    def test_error_handling(self):
        """
        测试错误处理机制
        """
        # 创建实例
        completer = DeepSeekTextCompleter(self.api_key, self.sample_data_path)
        
        # 模拟API调用失败
        with patch('requests.post', side_effect=requests.exceptions.RequestException("API调用失败")):
            result = completer.supplement_analysis(self.test_video_id, self.mock_vision_results)
        
        # 验证错误处理
        self.assertIn('text_supplement_error', result)
        self.assertIn('API调用失败', result['text_supplement_error'])
        self.assertIn('text_supplement_timestamp', result)
        
        # 验证原始视觉结果保持不变
        self.assertEqual(result['analysis']['视频标题']['value'], '跳舞短视频')
        self.assertEqual(result['analysis']['视频标题']['confidence'], 95)
    
    def test_confidence_based_merging(self):
        """
        测试基于置信度的结果合并逻辑
        """
        # 模拟API响应，包含不同置信度的补充结果
        mock_api_response = {
            "choices": [
                {
                    "message": {
                        "content": json.dumps({
                            "supplement_fields": {
                                "视频标题": {  # 置信度低于原始值，不应被替换
                                    "value": "流行舞蹈视频",
                                    "confidence": 85,
                                    "reasoning": "推测的标题"
                                },
                                "场景类型": {  # 原始值为None，应被替换
                                    "value": "室外",
                                    "confidence": 80,
                                    "reasoning": "推测的场景"
                                }
                            },
                            "overall_analysis": "测试分析"
                        })
                    }
                }
            ]
        }
        
        # 执行测试
        with patch('requests.post', return_value=MagicMock(json=lambda: mock_api_response, raise_for_status=lambda: None)):
            completer = DeepSeekTextCompleter(self.api_key, self.sample_data_path)
            result = completer.supplement_analysis(self.test_video_id, self.mock_vision_results)
        
        # 验证置信度高的原始值保留
        self.assertEqual(result['analysis']['视频标题']['value'], '跳舞短视频')  # 原始值保留
        self.assertEqual(result['analysis']['视频标题']['confidence'], 95)  # 原始置信度保留
        
        # 验证置信度高的补充值替换了空值
        self.assertEqual(result['analysis']['场景类型']['value'], '室外')  # 补充值被采纳
        self.assertEqual(result['analysis']['场景类型']['confidence'], 80)  # 补充置信度
    
    def test_integration_with_config_manager(self):
        """
        测试与配置管理器的集成
        """
        from src.config.config_manager import category_config_manager
        
        # 验证能够获取配置信息
        categories = category_config_manager.get_required_categories()
        self.assertIsInstance(categories, list)
        
        # 这个测试主要验证模块间的引用不会导致循环依赖问题
        # 实际的集成将在更高级别的测试中验证


if __name__ == '__main__':
    unittest.main()